package com.mq.mqserver.core;

import java.io.Serializable;
import java.util.Arrays;
import java.util.UUID;

/*
* （1）表示一个要传递的消息
* （2）一个mesage包含两个部分：属性部分 BasicProperties，正文部分 byte[] 正文支持二进制数据
* （3）此处的message对象，是需要能够在网络上传输，并且也需要能够写入文件的
*     此时就需要针对Message进行序列化和反序列化
*     此处使用标准库自带的 序列化/反序列化 操作，
*     备需要被序列化的类，要让他实现一个特定的接口Serializable,但是不重写方法
*     以往实现一个接口是为了重写接口方法，但是Serializable不需要重写任何方法
* （4）之前使用的json序列/反序列化 ，为啥不用json？
*      应为json本质是文本类型数据，而此处message存储的是二进制
*       序列/反序列化除了offsetBeg，offsetEnd
* */
public class Message implements Serializable {

    //最核心部分属性
    private BasicProperties basicProperties = new BasicProperties();
    private byte[] body;

    //下面是辅助属性
    /*
     （1）这一组属性，Message后续会存储到文件中（如果持久化的话）
     （2）为什么是文件不是数据库？
         因为消息不需要强大的增删改查功能；消息很多，需要频繁的增删改查，数据库效率低
     （3）一个文件中会存储很多很多的消息，如何找到这个消息的位置？
         使用下面的两个偏移量表示，[offsetBeg,offsetEnd),前闭后开
      （4）无需序列化保存到文件，因为消息一旦写入文件，位置就固定了，并不需要单独存储
      （5)这俩属性存在的目的是为了让内存中的message对象，能够快速找到对应硬盘的上方的message位置
      （6）transient描述的变量不可以被序列化
    */
    private transient long offsetBeg = 0;//消息数据的开头距离文件开头的位置偏移量（字节）
    private transient long offsetEnd = 0;////消息数据的结尾距离文件开头的位置偏移量（字节）
    /*
      （1）表示使用这个表示Message是否是有效消息（针对文件中的信息，幺十三处采用逻辑删除方式)
      （2）0x1表示有效。0x0表示无效
      （3）为什么不采用布尔型，因为是要存在硬盘上
    */
    private byte isValue = 0x1;

    /*
    * 创建一个工厂方法，让工厂帮我们封装一下Message对象过程
    * 这个方法中创建的Message对象，会自动生成唯一的MessageId
    * 万一routingKey和basicProperties里的rountingKey冲突，以外面的为主
    * */
    public static Message createMessageWithId(String routingKey,
                               BasicProperties basicProperties, byte[] body){
        Message message = new Message();
        if(basicProperties != null){
            message.setBasicProperties(basicProperties);
        }
        //此处生成的Meassage带有M前缀
        message.setMessageId("M-"+UUID.randomUUID().toString());
        message.basicProperties.setRountingKey(routingKey);
        message.body = body;
        //此处设置了basicProperties，body主属性
        //对于offsetBeg和offsetEnd，isValue是消息持久化的时候用到，在消息写入文件之前再设定
        //此处只是在内存中创建一个Message对象
        return message;

    }



    public String getMessageId(){
        return basicProperties.getMessageId();
    }
    public void setMessageId(String messageId){
        basicProperties.setMessageId(messageId);
    }
    public String getRountingKey(){
        return basicProperties.getRountingKey();
    }
    public void setRountingKey(String messageId){
        basicProperties.setRountingKey(messageId);
    }
    public int getDeliverMode(){
        return basicProperties.getDeliverMode();
    }
    public void setDeliverMode(int mode){
        basicProperties.setDeliverMode(mode);
    }
    public BasicProperties getBasicProperties() {
        return basicProperties;
    }

    public void setBasicProperties(BasicProperties basicProperties) {
        this.basicProperties = basicProperties;
    }

    public byte[] getBody() {
        return body;
    }

    public void setBody(byte[] body) {
        this.body = body;
    }

    public long getOffsetBeg() {
        return offsetBeg;
    }

    public void setOffsetBeg(long offsetBeg) {
        this.offsetBeg = offsetBeg;
    }

    public long getOffsetEnd() {
        return offsetEnd;
    }

    public void setOffsetEnd(long offsetEnd) {
        this.offsetEnd = offsetEnd;
    }

    public byte getIsValue() {
        return isValue;
    }

    public void setIsValue(byte isValue) {
        this.isValue = isValue;
    }

    @Override
    public String toString() {
        return "Message{" +
                "basicProperties=" + basicProperties +
                ", body=" + Arrays.toString(body) +
                ", offsetBeg=" + offsetBeg +
                ", offsetEnd=" + offsetEnd +
                ", isValue=" + isValue +
                '}';
    }
}
